package com.key.win.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.key.win.base.auth.AuthenticationUtil;
import com.key.win.base.auth.detail.Authentication;
import com.key.win.base.exception.BizException;
import com.key.win.base.exception.UserIllegalException;
import com.key.win.base.exception.login.AccountDisabledException;
import com.key.win.base.exception.login.AccountException;
import com.key.win.base.exception.login.AccountNotFoundException;
import com.key.win.base.exception.login.BadCredentialsException;
import com.key.win.base.page.MybatisPageServiceTemplate;
import com.key.win.base.util.BeanUtils;
import com.key.win.base.util.SingleSoldierConstantUtils;
import com.key.win.base.util.UUIDUtils;
import com.key.win.base.web.CodeEnum;
import com.key.win.base.web.PageRequest;
import com.key.win.base.web.PageResult;
import com.key.win.business.chat.dao.ImGroupUserDao;
import com.key.win.business.chat.eums.ImGroupTypeEnum;
import com.key.win.business.chat.model.ImGroupUser;
import com.key.win.business.chat.vo.ImGroupUserFullVo;
import com.key.win.common.websocket.utils.BroadcastMessageUtil;
import com.key.win.config.MyPasswordEncoder;
import com.key.win.system.dao.*;
import com.key.win.system.enums.UserTypeEnum;
import com.key.win.system.model.*;
import com.key.win.system.service.SysDeviceService;
import com.key.win.system.service.SysUserService;
import com.key.win.system.vo.DataPermissionVo;
import com.key.win.system.vo.RefreshTokenVo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUser> implements SysUserService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());


    @Autowired
    private MyPasswordEncoder myPasswordEncoder;

    @Autowired
    private SysOrganUserDao sysOrganUserDao;

    @Autowired
    private SysUserOrganDao sysUserOrganDao;

    @Autowired
    private SysUserDeviceDao sysUserDeviceDao;

    @Autowired
    private SysUserRoleDao sysUserRoleDao;

    @Autowired
    private SysUserGroupDao sysUserGroupDao;

    @Autowired
    private SysRolePermissionDao sysRolePermissionDao;

    @Autowired
    private SysRoleMenuDao sysRoleMenuDao;

    @Autowired
    private SysPermissionDao sysPermissionDao;

    @Autowired
    private SysMenuDao sysMenuDao;

    @Autowired
    private SysOrganDeviceDao sysOrganDeviceDao;

    @Autowired
    private ImGroupUserDao imGroupUserDao;

    @Autowired
    private SysDeviceService sysDeviceService;


    public void setUserToOrgan(String id, List<SysOrganUser> sysOrganUsers) {
        if (!CollectionUtils.isEmpty(sysOrganUsers)) {
            sysOrganUserDao.deleteOrganUser(null, id);
            sysOrganUserDao.saveBatchUserOrgans(id, sysOrganUsers);
            /*for (String menuId : menuIds) {
            /*for (String menuId : menuIds) {
                SysRoleMenu sysRoleMenu = new SysRoleMenu();
                sysRoleMenu.setRoleId(roleId);
                sysRoleMenu.setMenuId(menuId);
                sysRoleMenuDao.insert(sysRoleMenu);
            }*/
        }
    }

    @Override
    public boolean updateSysUser(SysUser sysUser) {
        if (StringUtils.isBlank(sysUser.getId())) {
            logger.error("用户id不存在");
            throw new IllegalArgumentException("用户id不存在!");
        }
        SysUser updateUser = this.getById(sysUser.getId());
        if (updateUser == null) {
            logger.error("用户不存在");
            throw new IllegalArgumentException("用户不存在!");
        }
        if (StringUtils.isNotBlank(sysUser.getUserName()) && !updateUser.getUserName().equals(sysUser.getUserName())) {
            logger.error("用户名非法，由{}被必为{}", updateUser.getUserName(), sysUser.getUserName());
            throw new IllegalArgumentException("用户名非法！");
        }
        // BeanUtils.copyProperties(sysUser, updateUser);
        // setOrganToUser(sysUser);
        setUserToOrgan(sysUser.getId(), sysUser.getSysOrganUserList());
        setDeviceToUser(sysUser);
        setRoleToUser(sysUser);
        setGroupToUser(sysUser);

        updateUser.setNickName(sysUser.getNickName());
        updateUser.setUpdateUserName(AuthenticationUtil.getUserName());
        updateUser.setUpdateUserId(AuthenticationUtil.getUserId());
        updateUser.setUpdateDate(new Date());
        updateUser.setVersion(sysUser.getVersion());
        updateUser.setPhone(sysUser.getPhone());
        updateUser.setType(sysUser.getType());
        updateUser.setSex(sysUser.getSex());
        updateUser.setHeadImgUrl(sysUser.getHeadImgUrl());
        return this.saveOrUpdate(updateUser);
    }

    private void setGroupToUser(SysUser sysUser) {
        if (StringUtils.isNotBlank(sysUser.getGroupId())) {
            Set<String> groupIds = Arrays.asList(sysUser.getGroupId().split(",")).stream().collect(Collectors.toSet());
            if (!CollectionUtils.isEmpty(groupIds)) {
                sysUserGroupDao.deleteUserGroup(sysUser.getId(), null);
                sysUserGroupDao.saveBatchUserIdAndGroupIds(sysUser.getId(), groupIds);
                /*groupIds.forEach(groupId -> {
                    SysUserGroup sysUserGroup = new SysUserGroup();
                    sysUserGroup.setGroupId(groupId);
                    sysUserGroup.setUserId(sysUser.getId());
                    sysUserGroupDao.insert(sysUserGroup);
                });*/
            }
        }
    }

    private void setRoleToUser(SysUser sysUser) {
        if (StringUtils.isNotBlank(sysUser.getRoleId())) {
            Set<String> roleIds = Arrays.asList(sysUser.getRoleId().split(",")).stream().collect(Collectors.toSet());
            if (!CollectionUtils.isEmpty(roleIds)) {
                sysUserRoleDao.deleteUserRole(sysUser.getId(), null);
                sysUserRoleDao.saveBatchUserIdAndRoleIds(sysUser.getId(), roleIds);
                /*roleIds.forEach(roleId -> {
                    SysUserRole sysUserRole = new SysUserRole();
                    sysUserRole.setRoleId(roleId);
                    sysUserRole.setUserId(sysUser.getId());
                    sysUserRoleDao.insert(sysUserRole);
                });*/
            }
        }
    }

    private void setDeviceToUser(SysUser sysUser) {
//        if (StringUtils.isNotBlank(sysUser.getDeviceId())) {
//            Set<String> deviceIds = Arrays.asList(sysUser.getDeviceId().split(",")).stream().collect(Collectors.toSet());
//            if (!CollectionUtils.isEmpty(deviceIds)) {
//                sysUserDeviceDao.deleteUserDevice(sysUser.getId(), null);
//                sysUserDeviceDao.saveBatchUserIdAndDeviceIds(sysUser.getId(), deviceIds);
//                /*deviceIds.forEach(deviceId -> {
//                    SysUserDevice sysUserDevice = new SysUserDevice();
//                    sysUserDevice.setUserId(sysUser.getId());
//                    sysUserDevice.setDeviceId(deviceId);
//                    sysUserDeviceDao.insert(sysUserDevice);
//                });*/
//            }
//        }
        List<SysUserDevice> sysUserDevices = sysUser.getSysUserDevices();
        if (!CollectionUtils.isEmpty(sysUserDevices)) {
            Set<String> organIds = sysUserDevices.stream().map(SysUserDevice::getOrganId).collect(Collectors.toSet());
            for (String organId : organIds) {
                sysUserDeviceDao.deleteUserDevice(sysUser.getId(), organId, null);
            }
            sysUserDeviceDao.saveBatchUserIdAndOrganIdsAndDeviceIds(sysUser.getId(), sysUserDevices);
        }
    }

    private void setOrganToUser(SysUser sysUser) {
        if (StringUtils.isNotBlank(sysUser.getOrganId())) {
            Set<String> organIds = Arrays.asList(sysUser.getOrganId().split(",")).stream().collect(Collectors.toSet());
            if (!CollectionUtils.isEmpty(organIds)) {
                sysOrganUserDao.deleteOrganUser(sysUser.getId(), null);
                sysOrganUserDao.saveBatchUserIdAndOrganIds(sysUser.getId(), organIds);
                /*organIds.forEach(organId -> {
                    SysUserOrgan sysUserRole = new SysUserOrgan();
                    sysUserRole.setUserId(sysUser.getId());
                    sysUserRole.setOrganId(organId);
                    sysUserOrganDao.insert(sysUserRole);
                });*/
            }
        }
    }

    @Override
    public PageResult<SysUser> findSysUserByPaged(PageRequest<SysUser> t) {
        MybatisPageServiceTemplate<SysUser, SysUser> mybatiesPageServiceTemplate = new MybatisPageServiceTemplate<SysUser, SysUser>(this.baseMapper) {
            @Override
            protected AbstractWrapper constructWrapper(SysUser sysUser) {
                LambdaQueryWrapper<SysUser> lqw = new LambdaQueryWrapper<SysUser>();
                if (sysUser != null) {
                    if (StringUtils.isNotBlank(sysUser.getNickName())) {
                        lqw.like(SysUser::getNickName, sysUser.getNickName());
                    }
                    if (StringUtils.isNotBlank(sysUser.getUserName())) {
                        lqw.like(SysUser::getUserName, sysUser.getUserName());
                    }
                }
                return lqw;
            }
        };
        return mybatiesPageServiceTemplate.doPagingQuery(t);
    }

    public List<SysUser> findSysUserByUserName(String userName) {
        LambdaQueryWrapper<SysUser> lqw = new LambdaQueryWrapper<SysUser>();
        lqw.eq(SysUser::getUserName, userName);
        List<SysUser> list = this.list(lqw);
        return list;
    }

    @Override
    public Map<String, Object> refreshToken(String token, String userAgent) {
        RefreshTokenVo refreshTokenVo = AuthenticationUtil.getRefreshTokenToRedis(token);
        logger.info("根据[{}]刷新token", token);
        if (refreshTokenVo == null) {
            logger.error("refreshToken is null !!");
            throw new UserIllegalException("refreshToken过期");
        }
        if (StringUtils.isBlank(refreshTokenVo.getUserName())) {
            logger.error("refreshToken中的userName is null !!");
            throw new UserIllegalException("refreshToken过期");
        }
        if (StringUtils.isBlank(refreshTokenVo.getToken())) {
            logger.error("refreshToken中的token is null !!");
            throw new UserIllegalException("refreshToken过期");
        }
        logger.info("根据[{}]刷新找到[token:{}][userName:{}]", refreshTokenVo.getUserName(), refreshTokenVo.getToken());
        List<SysUser> list = this.findSysUserByUserName(refreshTokenVo.getUserName());
        SysUser dbUser = list.get(0);
        checkIsEnabled(dbUser);
        Authentication loginUser = new Authentication();
        setUserExtinfo(userAgent, dbUser, loginUser);

        /**
         * 更新refreshtoken
         */
        if (AuthenticationUtil.isIsRefreshSelf()) {
            AuthenticationUtil.deleteRefreshTokenToRedis(token);
            //get new refresh token
            token = UUIDUtils.getGUID();
        }
        /**
         * 如果用户未失效的情况下刷新token
         * 则删除已经有用户信息
         */
        Authentication authentication = AuthenticationUtil.getAuthenticationToRedis(refreshTokenVo.getToken());
        if (authentication != null) {
            AuthenticationUtil.deleteTokenToRedis(refreshTokenVo.getToken());
        }

        return createToken(loginUser, token);
    }

    private void checkIsEnabled(SysUser dbUser) {
        if (!dbUser.getEnabled()) {
            logger.error("用户{}帐号被禁用", dbUser.getUserName());
            throw new AccountDisabledException("您的帐号被禁用！");
        }
    }

    @Override
    public Map<String, Object> login(SysUser sysUser, String userAgent) {
        List<SysUser> list = this.findSysUserByUserName(sysUser.getUserName());
        if (list == null || list.size() == 0) {
            logger.error("{}用户不存在！", sysUser.getUserName());
            throw new AccountNotFoundException("用户名或密码有误！");
        }
        if (list.size() > 1) {
            logger.error("{}用户存在{}个", sysUser.getUserName(), list.size());
            throw new AccountException("帐号不唯一,请联系管理员！");
        }

        SysUser dbUser = list.get(0);
        String encode = myPasswordEncoder.encode(sysUser.getPassword());
        if (!encode.equals(dbUser.getPassword())) {
            logger.error("用户{}的密码有误", dbUser.getUserName());
            throw new BadCredentialsException("用户名或密码有误！");
        }
        checkIsEnabled(dbUser);
        Authentication loginUser = new Authentication();
        setUserExtinfo(userAgent, dbUser, loginUser);
        //广播
        BroadcastMessageUtil.asyncBroadcastUserStatus(loginUser);
        String refreshToken = UUIDUtils.getGUID();
        return createToken(loginUser, refreshToken);
    }

    private Map<String, Object> createToken(Authentication loginUser, String refreshToken) {
        String guid = UUIDUtils.getGUID();
        loginUser.setToken(guid);
        loginUser.setOnLine(true);
        loginUser.setRefreshToken(refreshToken);
        loginUser.setDataPermissionVo(this.getCurrentUserDataPermissions(loginUser));
        //缓存用户
        AuthenticationUtil.setAuthenticationToRedis(loginUser);
        AuthenticationUtil.setRefreshTokenToRedis(refreshToken, loginUser);
        return this.getUserToken(guid, refreshToken);
    }

    private void setUserExtinfo(String userAgent, SysUser dbUser, Authentication loginUser) {
        BeanUtils.copyProperties(dbUser, loginUser);
        List<SysGroup> groupByUserId = sysUserGroupDao.findGroupByUserId(dbUser.getId());
        List<SysOrgan> organByUserId = sysOrganUserDao.findOrganByUserId(dbUser.getId());
        List<SysRole> rolesByUserId = sysUserRoleDao.findRolesByUserId(dbUser.getId());
        List<SysDevice> deviceByUserId = sysUserDeviceDao.findDeviceByUserId(dbUser.getId());
        List<SysOrgan> userOrganByUserId = getOrganByUserId(dbUser.getId());
        loginUser.setSysGroups(groupByUserId);
        loginUser.setSysDevices(deviceByUserId);
        loginUser.setSysOrganUsers(organByUserId);
        loginUser.setSysRoles(rolesByUserId);
        loginUser.setSysUserOrgans(userOrganByUserId);
        if (!CollectionUtils.isEmpty(rolesByUserId)) {
            if (dbUser.getType() == UserTypeEnum.ADMIN) {
                List<SysPermission> permissionDaoByRoleIds = sysPermissionDao.selectList(null);
                List<SysMenu> menusByRoleIds = sysMenuDao.selectList(null);
                loginUser.setPermissions(permissionDaoByRoleIds);
                loginUser.setMenus(menusByRoleIds);
            } else {
                Set<String> roleIds = rolesByUserId.stream().map(SysRole::getId).collect(Collectors.toSet());
                List<SysPermission> permissionDaoByRoleIds = sysRolePermissionDao.findByRoleIds(roleIds);
                List<SysMenu> menusByRoleIds = sysRoleMenuDao.findMenusByRoleIds(roleIds);
                loginUser.setPermissions(permissionDaoByRoleIds);
                loginUser.setMenus(menusByRoleIds);
            }
            Collections.sort(loginUser.getMenus(), new Comparator<SysMenu>() {
                @Override
                public int compare(SysMenu o1, SysMenu o2) {
                    return o1.getSort() - o2.getSort();
                }
            });
        }
        setLoginType(loginUser, userAgent);
    }

    public List<SysOrgan> getOrganByUserId(String userId) {
        return sysUserOrganDao.findOrganByUserId(userId);
    }

    private void setLoginType(Authentication loginUser, String info) {
        if (info.contains("Windows")) {
            loginUser.setLoginType("Windows");
        } else if (info.contains("Macintosh")) {
            loginUser.setLoginType("Macintosh");
        } else if (info.contains("Android")) {
            loginUser.setLoginType("Android");
        } else if (info.contains("iPhone")) {
            loginUser.setLoginType("iPhone");
        } else if (info.contains("iPad")) {
            loginUser.setLoginType("iPad");
        } else {
            loginUser.setLoginType("Other");
        }
    }

    public Map<String, Object> getUserToken(String token, String refreshToken) {
        Map<String, Object> userTokenVo = new HashMap<>();
        userTokenVo.put(SingleSoldierConstantUtils.REQUEST_TOKEN_KEY, token);
        userTokenVo.put(SingleSoldierConstantUtils.TOKEN_EXPIRES_IN_KEY, AuthenticationUtil.getTokenExpires());
        userTokenVo.put(SingleSoldierConstantUtils.TOKEN_BEARER_KEY, SingleSoldierConstantUtils.TOKEN_BEARER_VAUE);
        userTokenVo.put(SingleSoldierConstantUtils.REFRESH_TOKEN_KEY, refreshToken);
        return userTokenVo;
    }

    @Override
    public List<SysUser> findSysUserByOrganId(String organId) {
        return sysOrganUserDao.findUserByOrganId(organId);
    }

    @Override
    public boolean saveSysUser(SysUser sysUser) {
        List<SysUser> existUsers = this.findSysUserByUserName(sysUser.getUserName());
        if (!CollectionUtils.isEmpty(existUsers)) {
            logger.error("{}用户已经存在!", sysUser.getUserName());
            throw new BizException("用户已经存在！");
        }
        sysUser.setPassword(myPasswordEncoder.encode(SingleSoldierConstantUtils.RESET_PASSWORD));
        boolean b = this.saveOrUpdate(sysUser);
        // setOrganToUser(sysUser);
        setUserToOrgan(sysUser.getId(), sysUser.getSysOrganUserList());
        setDeviceToUser(sysUser);
        setRoleToUser(sysUser);
        return b;
    }

    @Override
    public boolean modifyPassword(SysUser sysUser) {
        SysUser user = this.getById(sysUser.getId());
        if (user == null) {
            logger.error("id为{}的用户不存在数据库中！", sysUser.getId());
            throw new IllegalArgumentException("用户不存在！");
        }
        user.setPassword(myPasswordEncoder.encode(sysUser.getNewPassword()));
        return this.saveOrUpdate(user);
    }

    @Override
    public boolean resetPassword(String id) {
        SysUser user = this.getById(id);
        if (user == null) {
            logger.error("id为{}的用户不存在数据库中！", id);
            throw new BizException("用户不存在！");
        }
        user.setPassword(myPasswordEncoder.encode(SingleSoldierConstantUtils.RESET_PASSWORD));
        return this.saveOrUpdate(user);
    }

    @Override
    public void setUserToGroup(String groupId, Set<String> userIds) {
        if (!CollectionUtils.isEmpty(userIds)) {
            sysUserGroupDao.deleteUserGroup(null, groupId);
            sysUserGroupDao.saveBatchUserIdsAndGroupId(userIds, groupId);
            /*for (String userId : userIds) {
                SysUserGroup sysUserGroup = new SysUserGroup();
                sysUserGroup.setGroupId(groupId);
                sysUserGroup.setUserId(userId);
                sysUserGroupDao.insert(sysUserGroup);
            }*/
        }
    }

    @Override
    public List<SysUser> findSysUserByGroupId(String groupId) {
        return sysUserGroupDao.findUserByGroupId(groupId);
    }

    @Override
    public PageResult<SysUser> getUserPagedByOrganId(PageRequest<SysUser> pageRequest) {
        if (StringUtils.isNotBlank(pageRequest.getT().getOrganId())) {
            IPage<SysUser> page = new Page<>();
            page.setSize(pageRequest.getPageSize());
            page.setCurrent(pageRequest.getPageNo());
            List<SysUser> userPagedByOrganId = sysOrganUserDao.findUserPagedByOrganId(page, pageRequest.getT().getOrganId());
            PageResult<SysUser> pageResult = new PageResult<>();
            pageResult.setCount(page.getTotal());
            pageResult.setPageNo(pageRequest.getPageNo());
            pageResult.setPageSize(pageRequest.getPageSize());
            pageResult.setData(userPagedByOrganId);
            pageResult.setCode(CodeEnum.SUCCESS.getCode());
            return pageResult;
        } else {
            return this.findSysUserByPaged(pageRequest);
        }
    }

    @Override
    public SysUser getUserFullById(String id) {
        SysUser byId = this.getById(id);
        byId.setSysRoles(sysUserRoleDao.findRolesByUserId(id));
        byId.setSysOrganUsers(sysOrganUserDao.findOrganByUserId(id));
        byId.setSysDevices(sysUserDeviceDao.findDeviceByUserId(id));
        byId.setSysGroups(sysUserGroupDao.findGroupByUserId(id));
        List<SysOrgan> sysOrganUsers = byId.getSysOrganUsers();
        if (!CollectionUtils.isEmpty(sysOrganUsers)) {
            String organIds = sysOrganUsers.stream().map(SysOrgan::getId).collect(Collectors.joining(","));
            byId.setOrganId(organIds);
        }
        if (!CollectionUtils.isEmpty(byId.getSysDevices())) {
            String deviceIds = byId.getSysDevices().stream().map(SysDevice::getId).collect(Collectors.joining(","));
            byId.setDeviceId(deviceIds);
        }
        if (!CollectionUtils.isEmpty(byId.getSysGroups())) {
            String groupIds = byId.getSysGroups().stream().map(SysGroup::getId).collect(Collectors.joining(","));
            byId.setGroupId(groupIds);
        }
        if (!CollectionUtils.isEmpty(byId.getSysRoles())) {
            String roleIds = byId.getSysRoles().stream().map(SysRole::getId).collect(Collectors.joining(","));
            byId.setRoleId(roleIds);
        }
        return byId;
    }

    @Override
    public boolean deleteById(String id) {
        SysUser userFullById = this.getUserFullById(id);
        List<SysOrgan> sysOrgans = userFullById.getSysOrganUsers();
        List<SysRole> sysRoles = userFullById.getSysRoles();
        List<SysDevice> sysDevices = userFullById.getSysDevices();
        List<SysGroup> sysGroups = userFullById.getSysGroups();
        if (!CollectionUtils.isEmpty(sysOrgans)) {
            logger.error("删除用户[{}]时，发现已关联SysOrgan！", id);
            throw new BizException("请先解除关联的机构信息！");
        }
        if (!CollectionUtils.isEmpty(sysRoles)) {
            logger.error("删除用户[{}]时，发现已关联SysRole信息！", id);
            throw new BizException("请先解除关联的角色信息！");
        }
        if (!CollectionUtils.isEmpty(sysDevices)) {
            logger.error("删除用户[{}]时，发现已关联SysDevice信息！", id);
            throw new BizException("请先解除关联的设备信息！");
        }
        if (!CollectionUtils.isEmpty(sysGroups)) {
            logger.error("删除用户[{}]时，发现已关联SysGroup信息！", id);
            throw new BizException("请先解除关联的用户组信息！");
        }
        return this.removeById(id);
    }

    @Override
    public boolean updateEnabled(SysUser sysUser) {
        if (StringUtils.isBlank(sysUser.getId())) {
            logger.error("用户id不存在");
            throw new IllegalArgumentException("用户id不存在!");
        }
        SysUser appUser = this.getById(sysUser.getId());
        if (appUser == null) {
            logger.error("用户不存在！");
            throw new BizException("用户不存在！");
        }
        appUser.setEnabled(sysUser.getEnabled());

        return this.saveOrUpdate(appUser);
    }

    @Override
    public void setOrganToUser(String id, Set<String> organIds) {
        if (!CollectionUtils.isEmpty(organIds)) {
            sysUserOrganDao.deleteUserOrgan(id, null);
            sysOrganUserDao.saveBatchUserIdAndOrganIds(id, organIds);
            /*for (String menuId : menuIds) {
                SysRoleMenu sysRoleMenu = new SysRoleMenu();
                sysRoleMenu.setRoleId(roleId);
                sysRoleMenu.setMenuId(menuId);
                sysRoleMenuDao.insert(sysRoleMenu);
            }*/
        }
    }

    public List<SysOrganUser> getSysOrganUserByCurrentUser() {
        LambdaQueryWrapper<SysOrganUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysOrganUser::getUserId, AuthenticationUtil.getUserId());
        List<SysOrganUser> sysOrganUsers = sysOrganUserDao.selectList(queryWrapper);
        return sysOrganUsers;
    }

    private DataPermissionVo getCurrentUserDataPermissions(Authentication authentication) {
        //Authentication authentication = AuthenticationUtil.getAuthentication();
        Map<String, SysDevice> sysDeviceHashMap = new HashMap<>();
        Map<String, SysUser> sysUserMap = new HashMap<>();
        //用户所持有的设备
        Map<String, Map<String, SysDevice>> userIdSysDeviceMap = new HashMap<>();
        //用户所持有的组
        Map<String, Map<String, ImGroupUserFullVo>> userIdGropMap = new HashMap<>();
        //当前用户所以管理的组
        Map<String, ImGroupUserFullVo> groups = new HashMap<>();
        //获取当前人被挂载的机构
        List<SysOrganUser> sysOrganUsers = getSysOrganUserByCurrentUser();
        if (!CollectionUtils.isEmpty(sysOrganUsers)) {
            for (SysOrganUser sysOrganUser : sysOrganUsers) {
                //如果当前是管理员
                if (sysOrganUser.getAdministrativePermissions()) {
                    //获取当前机构信息
                    getDevicesAndUsersByCurrentUser(sysDeviceHashMap, sysUserMap, userIdSysDeviceMap, sysOrganUser.getOrganId());

                } else {
                    //把人员信息优点到sysUserMap
                    getDevicesByUserId(authentication, sysDeviceHashMap, sysUserMap, userIdSysDeviceMap);
                }
                //获取当前人所管理的节点
                getUsersByUserId(sysDeviceHashMap, sysUserMap, userIdSysDeviceMap, sysOrganUser.getUserId());
            }
        } else {
            getDevicesByUserId(authentication, sysDeviceHashMap, sysUserMap, userIdSysDeviceMap);
            getUsersByUserId(sysDeviceHashMap, sysUserMap, userIdSysDeviceMap, AuthenticationUtil.getUserId());
        }

        getImGroupByCurrent(sysUserMap, userIdGropMap, groups);
        DataPermissionVo dataPermissionVo = new DataPermissionVo();
        dataPermissionVo.setDevices(sysDeviceHashMap);
        dataPermissionVo.setGroups(groups);
        dataPermissionVo.setUserIdGropMap(userIdGropMap);
        dataPermissionVo.setUserIdSysDeviceMap(userIdSysDeviceMap);
        dataPermissionVo.setUsers(sysUserMap);
        return dataPermissionVo;
    }

    private void getUsersByUserId(Map<String, SysDevice> sysDeviceHashMap, Map<String, SysUser> sysUserMap, Map<String, Map<String, SysDevice>> userIdSysDeviceMap, String userId) {
        //获取当前人所管理的节点
        List<SysOrgan> organByUserId = sysUserOrganDao.findOrganByUserId(userId);
        if (!CollectionUtils.isEmpty(organByUserId)) {
            for (SysOrgan sysOrgan : organByUserId) {
                getDevicesAndUsersByCurrentUser(sysDeviceHashMap, sysUserMap, userIdSysDeviceMap, sysOrgan.getId());
            }
        }
    }

    private void getDevicesByUserId(Authentication authentication, Map<String, SysDevice> sysDeviceHashMap, Map<String, SysUser> sysUserMap, Map<String, Map<String, SysDevice>> userIdSysDeviceMap) {
        //把人员信息优点到sysUserMap
        SysUser sysUser = new SysUser();
        sysUser.setId(authentication.getId());
        sysUser.setNickName(authentication.getNickName());
        sysUser.setUserName(authentication.getUserName());
        sysUserMap.put(authentication.getId(), sysUser);
        //如果当前人不是管理员，就获取自己所持有的设备。
        List<SysDevice> sysDevices = authentication.getSysDevices();
        if (!CollectionUtils.isEmpty(sysDevices)) {
            Map<String, SysDevice> collect1 = sysDevices.stream().collect(Collectors.toMap(SysDevice::getId, a -> a, (k1, k2) -> k1));
            sysDeviceHashMap.putAll(collect1);
            userIdSysDeviceMap.put(authentication.getId(), collect1);
        }
    }

    private void getDevicesAndUsersByCurrentUser(Map<String, SysDevice> sysDeviceHashMap, Map<String, SysUser> sysUserMap, Map<String, Map<String, SysDevice>> userIdSysDeviceMap, String id) {
        //获取当前机构信息
        List<SysDevice> deviceByOrganId = sysOrganDeviceDao.findDeviceByOrganId(id);
        //把当前机构的所持有的设备保存到sysDeviceHashMap
        if (!CollectionUtils.isEmpty(deviceByOrganId)) {
            Map<String, SysDevice> collect = deviceByOrganId.stream().collect(Collectors.toMap(SysDevice::getId, a -> a, (k1, k2) -> k1));
            sysDeviceHashMap.putAll(collect);
        }
        //根据当前机构Id，获取当前机构下边的所有人员信息
        List<SysUser> userByOrganId = sysOrganUserDao.findUserByOrganId(id);
        if (!CollectionUtils.isEmpty(userByOrganId)) {
            //把人员信息保存到sysUserMap
            Map<String, SysUser> collect = userByOrganId.stream().collect(Collectors.toMap(SysUser::getId, a -> a, (k1, k2) -> k1));
            sysUserMap.putAll(collect);
            //根据当前机构所拥有的人，来获取用户持有的设备
            List<String> userIdsByOrganId = userByOrganId.stream().map(SysUser::getId).collect(Collectors.toList());
            List<SysDevice> deviceByUserIds = sysUserDeviceDao.findDeviceByUserIds(userIdsByOrganId);
            if (!CollectionUtils.isEmpty(deviceByUserIds)) {
                for (SysDevice sysDevice : deviceByUserIds) {
                    String userId = sysDevice.getUserId();
                    Map<String, SysDevice> dmap = userIdSysDeviceMap.get(userId);
                    if (dmap == null) {
                        dmap = new HashMap<>();
                        userIdSysDeviceMap.put(userId, dmap);
                    }
                    dmap.put(sysDevice.getId(), sysDevice);
                }
            }
        }
    }

    //获取当前人所参与的组
    private void getImGroupByCurrent(Map<String, SysUser> sysUserMap, Map<String, Map<String, ImGroupUserFullVo>> userIdGropMap, Map<String, ImGroupUserFullVo> groups) {
        QueryWrapper<ImGroupUser> lambdaQueryWrapper = new QueryWrapper<>();
        lambdaQueryWrapper.in("gu.user_Id", sysUserMap.keySet());
        List<ImGroupUserFullVo> myGroupUser = imGroupUserDao.findMyGroupUser(lambdaQueryWrapper);
        if (!CollectionUtils.isEmpty(myGroupUser)) {
            Map<String, ImGroupUserFullVo> allGroup = myGroupUser.stream().filter(imGroupUserFullVo -> imGroupUserFullVo.getType() != ImGroupTypeEnum.NORMAL).collect(Collectors.toMap(ImGroupUserFullVo::getGroupId, a -> a, (k1, k2) -> k1));
            groups.putAll(allGroup);
            Map<String, Map<String, ImGroupUserFullVo>> collect = myGroupUser.stream().filter(imGroupUserFullVo -> imGroupUserFullVo.getType() != ImGroupTypeEnum.NORMAL).collect(Collectors.toMap(ImGroupUserFullVo::getUserId, p -> {
                Map<String, ImGroupUserFullVo> map = new HashMap();
                map.put(p.getId(), p);
                return map;
            }, (Map<String, ImGroupUserFullVo> value1, Map<String, ImGroupUserFullVo> value2) -> {
                value1.putAll(value2);
                return value1;
            }));
            userIdGropMap.putAll(collect);
        }
    }
}
